package com.csci.feishuapp.demo3.controller;

import com.csci.feishuapp.demo3.model.Identity;
import com.csci.feishuapp.demo3.model.Token;
import com.csci.feishuapp.demo3.utils.CustomGsonBuilder;
import com.google.gson.Gson;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.util.EntityUtils;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;

@Controller
@RequestMapping(value = "/")
public class DemoController {
    private final Gson gson = CustomGsonBuilder.createGson(); //new Gson();
    private final String baseUrl = "https://goon.csci.com.hk/zhtappsso-test";
    //private final String baseUrl = "http://10.1.18.172/zhtappsso";
    private final String appCode = "demo3";
    private final String appSecret = "sDRqiinr3pNst4NNsyYkXfIEA5zXImDy";

    @GetMapping(value = "authLogin")
    public String authLogin(HttpServletRequest request, HttpServletResponse response, Model model) throws IOException, NoSuchAlgorithmException, KeyManagementException {
        String code = request.getParameter("code");
        String state = request.getParameter("state");
        Token token = getAccessToken(code, state);
        if(token!=null) {
            Identity identity = getIdentity(token.accessToken);
            model.addAttribute("code", code);
            model.addAttribute("username", identity.username);
            model.addAttribute("realName", identity.realName);
            return "index";
        }
        model.addAttribute("message", "获取访问令牌失败");
        return "error";
    }

    public Token getAccessToken(String code, String state) throws IOException, KeyManagementException, NoSuchAlgorithmException {
        final String url = baseUrl+"/api/token";
        //参考文档：https://mkyong.com/java/apache-httpclient-examples/
        HttpPost post = new HttpPost(url);
        post.addHeader("content-type", "application/json");

        StringBuilder json = new StringBuilder();
        json.append("{");
        json.append("\"code\":\""+code+"\",");
        json.append("\"appCode\":\""+appCode+"\",");
        json.append("\"appSecret\":\""+appSecret+"\",");
        json.append("\"state\":\""+state+"\"");
        json.append("}");
        post.setEntity(new StringEntity(json.toString()));

        //采用绕过验证的方式处理https请求
        SSLContext sslcontext = createIgnoreVerifySSL();

        //设置协议http和https对应的处理socket链接工厂的对象
        Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
                .register("http", PlainConnectionSocketFactory.INSTANCE)
                .register("https", new SSLConnectionSocketFactory(sslcontext))
                .build();
        PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
        HttpClients.custom().setConnectionManager(connManager);

        //创建自定义的httpclient对象
        try (CloseableHttpClient httpClient = HttpClients.custom().setConnectionManager(connManager).build(); //CloseableHttpClient httpClient = HttpClients.createDefault();
             CloseableHttpResponse response = httpClient.execute(post)){
            int statusCode = response.getStatusLine().getStatusCode();
            if(statusCode>=200 && statusCode<300) {
                String result = EntityUtils.toString(response.getEntity());
                Token token = gson.fromJson(result, Token.class);
                return token;
            }
        }

        return null;
    }

    public Identity getIdentity(String accessToken) throws IOException, KeyManagementException, NoSuchAlgorithmException {
        final String url = baseUrl+"/api/validatetoken/"+accessToken;
        //参考文档：https://mkyong.com/java/apache-httpclient-examples/
        HttpGet get = new HttpGet(url);
        get.addHeader("content-type", "application/json");

        //采用绕过验证的方式处理https请求
        SSLContext sslcontext = createIgnoreVerifySSL();

        //设置协议http和https对应的处理socket链接工厂的对象
        Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
                .register("http", PlainConnectionSocketFactory.INSTANCE)
                .register("https", new SSLConnectionSocketFactory(sslcontext))
                .build();
        PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
        HttpClients.custom().setConnectionManager(connManager);

        //创建自定义的httpclient对象
        try (CloseableHttpClient httpClient = HttpClients.custom().setConnectionManager(connManager).build(); //CloseableHttpClient httpClient = HttpClients.createDefault();
             CloseableHttpResponse response = httpClient.execute(get)){
            int statusCode = response.getStatusLine().getStatusCode();
            if(statusCode>=200 && statusCode<300) {
                String result = EntityUtils.toString(response.getEntity());
                Identity identity = gson.fromJson(result, Identity.class);
                return identity;
            }
        }

        return null;
    }

    /**
     * 绕过验证
     *
     * @return
     * @throws NoSuchAlgorithmException
     * @throws KeyManagementException
     */
    public static SSLContext createIgnoreVerifySSL() throws NoSuchAlgorithmException, KeyManagementException {
        SSLContext sc = SSLContext.getInstance("SSLv3");

        // 实现一个X509TrustManager接口，用于绕过验证，不用修改里面的方法
        X509TrustManager trustManager = new X509TrustManager() {
            @Override
            public void checkClientTrusted(
                    java.security.cert.X509Certificate[] paramArrayOfX509Certificate,
                    String paramString) throws CertificateException {
            }

            @Override
            public void checkServerTrusted(
                    java.security.cert.X509Certificate[] paramArrayOfX509Certificate,
                    String paramString) throws CertificateException {
            }

            @Override
            public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                return null;
            }
        };

        sc.init(null, new TrustManager[] { trustManager }, null);
        return sc;
    }
}
